package com.yonyou.pmclouds.basecom.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.yonyou.pmclouds.basecom.conf.NCInvokerConfiguration;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.billtype.entity.BillTypeRefVO;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * nc、ncc单据类型查询服务类
 *
 * @author th
 * @date 2019/11/20 10:14
 */
@Slf4j
@Component
public class NCBillTypeQueryService {
    public static final String BILL_TYPE_QUERY_SERVICE_NAME = "BillTypeDriveQueryServlet";
    public static final String NC_SERVICE_SERVLET_PATH = "/service/BillTypeDriveQueryServlet";
    public static final String NC_UBL_SERVICE = "nc.bs.pmcloud.servlet.ublimpl.BillTypeDriveQueryImp4UBL";

    @Autowired
    private ProjectSimpleQuery projectQuery;
    @Autowired
    private NCInvokerConfiguration.Invoker invoker;

    private ObjectMapper mapper = new ObjectMapper();

    /**
     * 为项目计划查询可关联的nc，ncc单据类型
     *
     * @return
     * @throws BusinessException
     */
    public BillTypeRefVO[] queryRelatedBillTypeForPlan() throws BusinessException {
        BillTypeRefVO[] refVOs = null;

        Map<String, Object> requestParams = new HashMap<>();
        // 返回结果
        NCInvokerConfiguration.Result invokeResult = null;
        Map resultMap;

        try {
            // 调用NC查询接口
            Future<NCInvokerConfiguration.Result> resultFuture = invoker.invokeAsync(BILL_TYPE_QUERY_SERVICE_NAME,
                    NC_SERVICE_SERVLET_PATH, requestParams, RuntimeEnvironment.getTenantId(),
                    RuntimeEnvironment.getLoginUserId(), null);

            // 阻塞，设置超时时间5秒
            invokeResult = resultFuture.get(5, TimeUnit.SECONDS);
            if (invokeResult == null || invokeResult.getResult() == null) {
                log.error("nc单据类型查询失败, 返回result: {}", invokeResult == null ? null : invokeResult.getResult());
                return new BillTypeRefVO[0];
            }

            if (!NCInvokerConfiguration.Result.STATUS_OK.equals(invokeResult.getStatus())) {
                log.error("nc单据类型查询失败, 返回status: {}, result: {}", invokeResult.getStatus(), invokeResult.getResult());
                return new BillTypeRefVO[0];
            }

            resultMap = mapper.readValue(invokeResult.getResult(), Map.class);
            if (!"ok".equals(resultMap.get("resultCode"))) {
                log.error("nc单据类型查询失败, 返回result: {}", resultMap.get("result"));
                return new BillTypeRefVO[0];
            }

            CollectionType listType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, ResultObject.class);
            List<ResultObject> resultObjects = mapper.readValue(JSON.toJSONString(resultMap.get("result")), listType);
            refVOs = transformToBillTypeRefVO(resultObjects);
        } catch (IOException e) {
            log.error("unserialization failed, result is {}", invokeResult.getResult());
            log.error("nc单据类型查询结果反序列失败", e);
            return new BillTypeRefVO[0];
        } catch (Exception e) {
            log.error("nc单据类型查询失败, 返回result: {}", invokeResult == null ? null : invokeResult.getResult());
            log.error("nc单据类型查询失败", e);
            return new BillTypeRefVO[0];
        }

        return refVOs;
    }

    /**
     * 将返回的结果转换成前台显示的单据类型参照VO
     *
     * @param resultObjects
     * @return
     */
    private BillTypeRefVO[] transformToBillTypeRefVO(List<ResultObject> resultObjects) {
        if (CollectionUtils.isEmpty(resultObjects))
            return new BillTypeRefVO[0];

        BillTypeRefVO[] refVOs = new BillTypeRefVO[resultObjects.size()];
        ResultObject ro;
        for (int i = 0; i < resultObjects.size(); i++) {
            ro = resultObjects.get(i);
            refVOs[i] = new BillTypeRefVO(StringUtils.isEmpty(ro.getTransi_type()) ?
                    ro.getBill_type() : ro.getTransi_type(), ro.getPmc_show_name());
        }

        return refVOs;
    }

    @Data
    public static class ResultObject {
        private String pk_group;
        private String pk_org;
        private String bill_type;
        private String transi_type;
        private String pmc_show_name;
        private String ts;
    }

}
